package com.swsc.solarverse.common.util;

import java.time.Instant;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.format.DateTimeFormatter;
import java.time.temporal.ChronoUnit;
import java.time.temporal.TemporalAdjusters;
import java.util.TimeZone;
import java.util.regex.Pattern;

/**
 * @Author anonymous
 * @Date 2022/7/5 15:19
 * @Version 1.0
 * @Description LocalDateTimeUtils
 */
public class LocalDateTimeUtils {

    public static final String RGX_YYYY_MM_DD = "(([0-9]{3}[1-9]|[0-9]{2}[1-9][0-9]{1}|[0-9]{1}[1-9][0-9]{2}|[1-9][0-9]{3})-(((0[13578]|1[02])-(0[1-9]|[12][0-9]|3[01]))|"+
            "((0[469]|11)-(0[1-9]|[12][0-9]|30))|(02-(0[1-9]|[1][0-9]|2[0-8]))))|((([0-9]{2})(0[48]|[2468][048]|[13579][26])|"+
            "((0[48]|[2468][048]|[3579][26])00))-02-29)$";

    public static LocalDateTime ofMilli(long timemills){
        return LocalDateTime.ofInstant(Instant.ofEpochMilli(timemills),
                        TimeZone.getDefault().toZoneId());

    }

    public static LocalDateTime ofSecond(long timesec){
        return LocalDateTime.ofInstant(Instant.ofEpochSecond(timesec),
                TimeZone.getDefault().toZoneId());

    }

    public static LocalDateTime getHourStart(LocalDateTime dateTime){
        String dateStr = LocalDateTimeUtils.time2Str(dateTime, "yyyy-MM-dd");
        int hour = dateTime.getHour();
        dateStr = dateStr + " " + (hour < 10 ? "0" + hour : hour) + ":00:00";
        return str2Time(dateStr);
    }

    public static LocalDateTime getDayStart(LocalDateTime dateTime){
        return null == dateTime ? null : dateTime.with(LocalTime.MIN);
    }

    public static LocalDateTime getDayEnd(LocalDateTime dateTime){
        return null == dateTime ? null : dateTime.with(LocalTime.MAX);
    }

    public static LocalDateTime getMonthStart(LocalDateTime dateTime){
        return getDayStart(dateTime.with(TemporalAdjusters.firstDayOfMonth()));
    }

    public static LocalDateTime getMonthEnd(LocalDateTime dateTime){
        return getDayEnd(dateTime.with(TemporalAdjusters.lastDayOfMonth()));
    }

    public static LocalDateTime getYearStart(LocalDateTime dateTime){
        return getDayStart(dateTime.with(TemporalAdjusters.firstDayOfYear()));
    }

    public static LocalDateTime getYearEnd(LocalDateTime dateTime){
        return getDayEnd(dateTime.with(TemporalAdjusters.lastDayOfYear()));
    }

    public static LocalDateTime str2Time(String str){
        return str2Time(str, "yyyy-MM-dd HH:mm:ss");
    }

    public static LocalDateTime str2Time(String str, String pattern){
        if(Pattern.matches(RGX_YYYY_MM_DD, str)){
            str = str + " 00:00:00";
        }
        DateTimeFormatter dtf = DateTimeFormatter.ofPattern(pattern);
        return LocalDateTime.parse(str, dtf);
    }

    public static String time2Str(LocalDateTime time, String pattern){
        DateTimeFormatter dtf = DateTimeFormatter.ofPattern(pattern);
        return time.format(dtf);
    }

    public static String durationDays(LocalDateTime start, LocalDateTime end){
        if(null == start || null == end){
            return null;
        }
        return start.until(end, ChronoUnit.DAYS) + "天";
    }

    public static Long diff(LocalDateTime start, LocalDateTime end, ChronoUnit unit){
        if(null == start || null == end){
            return null;
        }
        if(null == unit){
            return start.until(end, ChronoUnit.MILLIS);
        }
        return start.until(end, unit);
    }

    public static long toMilli(LocalDateTime localDateTime){
        return localDateTime.atZone(java.time.ZoneId.systemDefault()).toInstant().toEpochMilli();
    }

    public static String parseDataTimeStr(LocalDateTime now, long before){
        // 往后倒退13分钟
        LocalDateTime dataTime = now.minusMinutes(before);
        int min = dataTime.getMinute();
        if(min >= 0 && min < 5){
            min = 0;
        }else if(min >= 5 && min < 10){
            min = 5;
        }else if(min >= 10 && min < 15){
            min = 10;
        }else if(min >= 15 && min < 20){
            min = 15;
        }else if(min >= 20 && min < 25){
            min = 20;
        }else if(min >= 25 && min < 30){
            min = 25;
        }else if(min >= 30 && min < 35){
            min = 30;
        }else if(min >= 35 && min < 40){
            min = 35;
        }else if(min >= 40 && min < 45){
            min = 40;
        }else if(min >= 45 && min < 50){
            min = 45;
        }else if(min >= 50 && min < 55){
            min = 50;
        }else if(min >= 55 && min < 60){
            min = 55;
        }
        return LocalDateTimeUtils.time2Str(dataTime, "yyyy-MM-dd HH").concat(":").concat(String.format("%02d", min)).concat(":00");
    }

    public static java.util.List<Integer[]> getYearMonthDayIntArr(LocalDateTime startDate, LocalDateTime endDate){
        Integer[] arr = null;
        if(null == startDate && null == endDate){
            LocalDateTime now = LocalDateTime.now();
            arr = new Integer[3];
            arr[0] = now.getYear();
            arr[1] = now.getMonthValue();
            arr[2] = now.getDayOfMonth();
            java.util.List<Integer[]> list = new java.util.ArrayList<>(1);
            list.add(arr);
            return list;
        }
        if(null == startDate && null != endDate){
            arr = new Integer[3];
            arr[0] = endDate.getYear();
            arr[1] = endDate.getMonthValue();
            arr[2] = endDate.getDayOfMonth();
            java.util.List<Integer[]> list = new java.util.ArrayList<>(1);
            list.add(arr);
            return list;
        }
        if(null != startDate && null == endDate){
            arr = new Integer[3];
            arr[0] = startDate.getYear();
            arr[1] = startDate.getMonthValue();
            arr[2] = startDate.getDayOfMonth();
            java.util.List<Integer[]> list = new java.util.ArrayList<>(1);
            list.add(arr);
            return list;
        }
        if(startDate.isAfter(endDate)){
            arr = new Integer[3];
            arr[0] = startDate.getYear();
            arr[1] = startDate.getMonthValue();
            arr[2] = startDate.getDayOfMonth();
            java.util.List<Integer[]> list = new java.util.ArrayList<>(1);
            list.add(arr);
            return list;
        }else {
            endDate = getDayStart(endDate);
            startDate = getDayStart(startDate);
            java.util.List<Integer[]> list = new java.util.ArrayList<>();
            while (endDate.isAfter(startDate) || endDate.equals(startDate)) {
                String dateStr = LocalDateTimeUtils.time2Str(startDate, "yyyy-MM-dd");
                String[] dateStrs = dateStr.split("-");
                Integer[] dayArr = new Integer[3];
                dayArr[0] = Integer.parseInt(dateStrs[0]);
                dayArr[1] = Integer.parseInt(dateStrs[1]);
                dayArr[2] = Integer.parseInt(dateStrs[2]);
                list.add(dayArr);
                startDate = startDate.plusDays(1L);
            }
            return list;
        }
    }
    private LocalDateTimeUtils(){}
}
